package com.example.aigc_education.security.filter;

import cn.hutool.core.bean.BeanDesc;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.aigc_education.constant.WeChatConstants;
import com.example.aigc_education.security.token.MobileAuthenticationToken;
import com.example.aigc_education.security.token.WeChatAuthenticationToken;
import com.example.aigc_education.utils.GetBeanUtil;
import com.example.aigc_education.utils.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@Slf4j
public class WeChatAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    private  WeChatConstants weChatConstants;

    private static final String WECHAT_CODE_PARAMETER = "wechatCode";
    private boolean postOnly = true;    // 默认请求方式只能为 POST

    //这也是一个认证路径，如果匹配到这个路径，就会走这个过滤器，但由于这个过滤器设置了普通的登录成功的处理器，所以与业务不符一般不会走这个路径
    public WeChatAuthenticationFilter() {
        super(new AntPathRequestMatcher("wechat/login", "POST")
        );
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        if(postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }else {
            //校验code
            String code = this.obtainCode(request);
            WeChatConstants weChatConstants = GetBeanUtil.getBean(WeChatConstants.class);
            this.weChatConstants = weChatConstants;
            //发送登录请求
            String  openid = getOpenid(code);

//            String openid = "oDPJf7L45EBzHlw7X9c-NIKpzZ5Q";
            log.info("openid:"+openid);
            //创建未认证token
            WeChatAuthenticationToken authRequest = new WeChatAuthenticationToken(openid);
            //验证token
            setDetails(request, authRequest);
            return this.getAuthenticationManager().authenticate(authRequest);
        }
    }

    /**
     * 调用微信接口服务，获得当前微信用户的openid
     * @param code
     * @return
     */
    private String getOpenid(String code){
        // 调用微信接口服务，获得当前微信用户的openid
        Map<String, String> map = new HashMap<>();
        map.put("appid", weChatConstants.getAppid());
        map.put("secret",weChatConstants.getSecret());
        map.put("js_code",code);
        map.put("grant_type","authorization_code");
        String WX_LOGIN = weChatConstants.getLoginUrl();
        String json = HttpClientUtil.doGet(WX_LOGIN, map); // 得到微信端服务器返回的json数据

        JSONObject jsonObject = JSON.parseObject(json);
        String openid = jsonObject.getString("openid"); // 解析json数据，获取openid

        return openid;
    }

    /**
     * 校验授权码code
     */
    private String obtainCode(HttpServletRequest request) {
        String code = request.getParameter(WECHAT_CODE_PARAMETER);
        return Optional.of(code).orElseThrow(() -> new AuthenticationServiceException("wechatCode is empty"));
    }


    protected void setDetails(HttpServletRequest request, WeChatAuthenticationToken authRequest) {
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }

}
